﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Graphics;

namespace PacCraft
{
    class Player
    {
        private Sprite3D    model;
        private Camera      camera;
        private char[][]    map;
        public bool debug = false;

        private BoundingBox box;
        private List<BoundingBox> wallBox = new List<BoundingBox>();

        private float vSpeed = 0.1f;
        private float rSpeed = 0.03f;

        private float reduceDim = 0.3f;

        public Player(GraphicsDeviceManager graphics, Map _map, Model _player)
        {
            model = new Sprite3D(_player);
            model.scale = new Vector3(0.005f, 0.008f, 0.005f);
            map = _map.map;
            camera = new Camera(graphics);
            initPosition();
            int curentX = (int)camera.position.X;
            int curentY = (int)camera.position.Y;
            box.Min = new Vector3(curentX - reduceDim, 2f, curentY - reduceDim);
            box.Max = new Vector3(curentX + reduceDim, 3f, curentY + reduceDim);
        }

        private void initPosition()
        {
            for (int i = 1; i < map.Length; ++i)
                for (int j = 1; j < map[i].Length; ++j)
                    if (map[i][j] == '0')
                    {
                        camera.position = new Vector2((float)i + 0.5f, (float)j + 0.5f);
                        model.position = new Vector3((float)i + 0.5f, 1f, (float)j + 0.5f);
                        return;
                    }
        }

        private bool moveTo(float nextX, float nextY)
        {
            BoundingBox nextBox = new BoundingBox();
            nextBox.Min = new Vector3(nextX - reduceDim, 2f, nextY - reduceDim);
            nextBox.Max = new Vector3(nextX + reduceDim, 3f, nextY + reduceDim);
            if (!doesIntersect(nextBox))
            {
                camera.position.X = nextX;
                camera.position.Y = nextY;
                box.Min = new Vector3(camera.position.X - reduceDim, 2f, camera.position.Y - reduceDim);
                box.Max = new Vector3(camera.position.X + reduceDim, 3f, camera.position.Y + reduceDim);
                return true;
            }
            return false;
        }

        public void move(Keys key)
        {
            if (key == Keys.Right)
                camera.orientation += rSpeed;
            if (key == Keys.Left)
                camera.orientation -= rSpeed;
            if (key == Keys.Up)
            {
                if (moveTo(camera.position.X + (vSpeed * (float)Math.Cos(camera.orientation)),
                    camera.position.Y + (vSpeed * (float)Math.Sin(camera.orientation))))
                    return;
                else if (!moveTo(camera.position.X + (vSpeed * (float)Math.Cos(camera.orientation)), camera.position.Y))
                    moveTo(camera.position.X, camera.position.Y + (vSpeed * (float)Math.Sin(camera.orientation)));
            }
            if (key == Keys.Down)
            {
                if (moveTo(camera.position.X - (vSpeed * (float)Math.Cos(camera.orientation)),
                    camera.position.Y - (vSpeed * (float)Math.Sin(camera.orientation))))
                    return;
                else if (!moveTo(camera.position.X - (vSpeed * (float)Math.Cos(camera.orientation)), camera.position.Y))
                    moveTo(camera.position.X, camera.position.Y - (vSpeed * (float)Math.Sin(camera.orientation)));
            }
        }

        private bool doesIntersect(BoundingBox nextBox)
        {
            List<BoundingBox> walls = new List<BoundingBox>();
            int currentX = (int) camera.position.X;
            int currentY = (int) camera.position.Y;
            Vector3 min;
            Vector3 max;
            if (debug)
                Console.WriteLine("CurrentY: " + currentY + ", float: " + camera.position.Y);

            for (int i = -1; i <= 1; ++i)
                for (int j = -1; j <= 1; ++j)
                {
                    if (currentX + i >= 0 && currentY + j >= 0 && map[currentX + i][currentY + j] == '1')
                    {
                        min = new Vector3(currentX + i, 0f, currentY + j);
                        max = new Vector3(currentX + i + 1, 5f, currentY + j + 1);

                        walls.Add(new BoundingBox(min, max));
                    }
                }
            wallBox = walls;
            foreach (BoundingBox wall in walls)
            {
                if (nextBox.Intersects(wall))
                {
                    if (debug)
                        Console.WriteLine("Il y a une collision" + wall.Min + wall.Max);
                    return true;
                }
            }
            return false;
        }

        public Vector2 getPosition()
        {
            return new Vector2(model.position.X, model.position.Z);
        }

        public BoundingBox getBox()
        {
            return box;
        }

        public void changeView()
        {
            if (++camera.vue > 1)
                camera.vue = 0;
        }

        public BasicEffect getCamera()
        {
            return camera.getCamera();
        }

        public void Draw()
        {
            model.position = new Vector3(camera.position.X, 1f, camera.position.Y);
            model.rotationY = -camera.orientation + (float)Math.PI / 2f;
            model.Draw(camera.basicEffect);
        }

        public void drawBox()
        {
            BoxRender.Render(box, camera.getCamera().GraphicsDevice, camera.getCamera().View, camera.getCamera().Projection, Color.White);
            foreach (BoundingBox wall in wallBox)
                BoxRender.Render(wall, camera.getCamera().GraphicsDevice, camera.getCamera().View, camera.getCamera().Projection, Color.White);
        }

    }
}
